package com.swf.seed.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * ClassName: ClassLoaderUtils <br/>
 * Function:  * 类描述： 用来加载类，classPath下的资源文件，属性文件等。
 *  getExtendResource(StringrelativePath)方法，可以使用../符号来加载classpath外部的资源。 <br/>
 * Reason: TODO ADD REASON(可选). <br/>
 * date: 2014-7-1 下午3:16:41 <br/>
 *
 * @author shenwf10476
 * @version 
 * @since JDK 1.6
 */
public final class ClassLoaderUtils {
    private static Logger logger=LoggerFactory.getLogger(ClassLoaderUtils.class);
    /**
     *Thread.currentThread().getContextClassLoader().getResource("")
     */
    
    /**
	 * 禁用默认构造器	
	 */
	private ClassLoaderUtils() {
	}
    /**
     *加载Java类。 使用全限定类名
     *@paramclassName
     *@return
     */
    public static Class loadClass(String className) {
        try {
          return getClassLoader().loadClass(className);
        } catch (ClassNotFoundException e) {
          throw new RuntimeException("class not found '"+className+"'", e);
        }
     }
     /**
       *得到类加载器
       *@return
       */
     public static ClassLoader getClassLoader() {
        return ClassLoaderUtils.class.getClassLoader();
     }
     /**
       *提供相对于classpath的资源路径，返回文件的输入流
       *@paramrelativePath必须传递资源的相对路径。是相对于classpath的路径。如果需要查找classpath外部的资源，需要使用../来查找
       *@return 文件输入流
     *@throwsIOException
     *@throwsMalformedURLException
       */
     public static InputStream getStream(String relativePath) throws MalformedURLException, IOException {
         if(!relativePath.contains("../")){
             return getClassLoader().getResourceAsStream(relativePath);
         }else{
             return ClassLoaderUtils.getStreamByExtendResource(relativePath);
         }
        
     }
     /**
       *
       *@paramurl
       *@return
       *@throwsIOException
       */
     public static InputStream getStream(URL url) throws IOException{
         if(url!=null){
                return url.openStream();
         }else{
             return null;
         }
     }
     /**
       *
       *@paramrelativePath必须传递资源的相对路径。是相对于classpath的路径。如果需要查找classpath外部的资源，需要使用../来查找
       *@return
       *@throwsMalformedURLException
       *@throwsIOException
       */
     public static InputStream getStreamByExtendResource(String relativePath) throws MalformedURLException, IOException{
        return ClassLoaderUtils.getStream(ClassLoaderUtils.getExtendResource(relativePath));
         
         
     }
     
      /**
       *提供相对于classpath的资源路径，返回属性对象，它是一个散列表
       *@paramresource
       *@return
       */
     public static Properties getProperties(String resource) {
        Properties properties = new Properties();
        try {
          properties.load(getStream(resource));
        } catch (IOException e) {
          throw new RuntimeException("couldn't load properties file '"+resource+"'", e);
        }
        return properties;
     }
     /**
       *得到本Class所在的ClassLoader的Classpath的绝对路径。
       *URL形式的
       *@return
       */
     public static String getAbsolutePathOfClassLoaderClassPath(){
         return ClassLoaderUtils.getClassLoader().getResource("").toString();
         
     }
     /**
       *
       *@paramrelativePath 必须传递资源的相对路径。是相对于classpath的路径。如果需要查找classpath外部的资源，需要使用../来查找
       *@return资源的绝对URL
     *@throwsMalformedURLException
       */
     public static URL getExtendResource(String relativePath) throws MalformedURLException{
     
    	 //如果没有../，说明在classpath下查找，直接调用JDK自带的getResource(path)就行了
         if(!relativePath.contains("../")){
             return ClassLoaderUtils.getResource(relativePath);
         }
         String classPathAbsolutePath=ClassLoaderUtils.getAbsolutePathOfClassLoaderClassPath();
         if(relativePath.substring(0, 1).equals("/")){
             relativePath=relativePath.substring(1);
         }
        
         String wildcardString=relativePath.substring(0,relativePath.lastIndexOf("../")+3);
         relativePath=relativePath.substring(relativePath.lastIndexOf("../")+3);
         int containSum=ClassLoaderUtils.containSum(wildcardString, "../");
         classPathAbsolutePath= ClassLoaderUtils.cutLastString(classPathAbsolutePath, "/", containSum);
         String resourceAbsolutePath=classPathAbsolutePath+relativePath;
         URL resourceAbsoluteURL=new URL(resourceAbsolutePath);
         return resourceAbsoluteURL;
     }
    
     private static int containSum(String source,String dest){
         int containSum=0;
         int destLength=dest.length();
         while(source.contains(dest)){
             containSum=containSum+1;
             source=source.substring(destLength);
             
         }
         
         
         return containSum;
     }
   
     
    /**  
     * method:cutLastString{按照../向上找到目录}  
     * @param source //源路径，一般为classPath路径
     * @param dest  //分隔符"/"
     * @param num  ../的个数
     * @return String 
     */
    private static String cutLastString(String source,String dest,int num){
         for(int i=0;i<num;i++){
             source=source.substring(0, source.lastIndexOf(dest, source.length()-2)+1);
         }
         return source;
     }
     
     /**
       *
       *@paramresource
       *@return
       */
      public static URL getResource(String resource){
         return ClassLoaderUtils.getClassLoader().getResource(resource);
     }
     
     /**
      * 获取文件
     * @param relativePath
     * @return
     */
    public static File getFile(String relativePath){
    	 try {
			URL url = getExtendResource(relativePath);
			if (url==null) {
				throw new FileNotFoundException("文件路径不存在");
			}
			File file = new File(url.toURI());
			if (file.exists()) {
				return file;
			}else{
				throw new FileNotFoundException("路径"+file.getAbsolutePath()+"下找不到文件");
			}
		} catch (MalformedURLException e) {
			logger.error(e.getMessage(), e);
		} catch (URISyntaxException e) {
			logger.error(e.getMessage(), e);
		} catch (FileNotFoundException e) {
			logger.error(e.getMessage(), e);
		}
		return null;
     }
     
    
    /** 根据相对路径获取绝对路径
     * @param relativePath
     * @return
     */
    public static String getAbsolutePath(String relativePath){
    	File file = getFile(relativePath);
    	return file==null?"":file.getAbsolutePath();
	}
 
}
